use apikit::{ApiError, StatusCode};
use log::{error, warn};
use thiserror::Error;

#[derive(Debug, Error, ApiError)]
#[error("请求参数错误")]
#[status_code(StatusCode::UNPROCESSABLE_ENTITY)]
pub struct EntityError(#[from] pub anyhow::Error);

pub trait MapEntityError {
    type T;
    fn map_entity_error(self) -> Result<Self::T, EntityError>;
}

impl<T, E: std::error::Error + Send + Sync + 'static> MapEntityError for Result<T, E> {
    type T = T;
    fn map_entity_error(self) -> Result<Self::T, EntityError> {
        self.map_err(|e| {
            warn!("请求参数错误: {:?}", e);
            EntityError(anyhow::Error::new(e))
        })
    }
}

#[derive(Debug, Error, ApiError)]
#[error("服务异常")]
#[status_code(StatusCode::INTERNAL_SERVER_ERROR)]
pub struct ServerError(#[from] pub anyhow::Error);

pub trait MapServerError {
    type T;
    fn map_server_error<E: From<ServerError>>(self) -> Result<Self::T, E>;
}

impl<T, E: Into<anyhow::Error>> MapServerError for Result<T, E> {
    type T = T;
    fn map_server_error<E1: From<ServerError>>(self) -> Result<Self::T, E1> {
        self.map_err(|e| ServerError(e.into()).into())
    }
}

#[derive(Debug, Error, ApiError)]
#[error("{0}")]
#[status_code(StatusCode::BAD_REQUEST)]
pub struct BadRequest(String);

pub fn bad_request<T, E: From<BadRequest>, M: Into<String>>(msg: M) -> Result<T, E> {
    let e = BadRequest::from(msg.into());
    Err(E::from(e))
}

impl From<String> for BadRequest {
    fn from(value: String) -> Self {
        BadRequest(value)
    }
}

#[derive(Debug, Error, ApiError)]
#[error("OK")]
#[status_code(status = 200, code = "0")]
pub struct Success;

#[derive(Debug, Error, ApiError)]
#[error("{0}")]
#[status_code(status = 200, code = "1000")]
pub struct BiError(String);
